package com.dong.oss.service;

import com.dong.oss.config.MinioProperties;
import io.minio.GetObjectArgs;
import io.minio.ListObjectsArgs;
import io.minio.MinioClient;
import io.minio.Result;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * MinIO服务类
 */
@Slf4j
@Service
public class MinioService {
    
    private final Optional<MinioClient> minioClient;
    private final MinioProperties minioProperties;
    
    public MinioService(@Autowired(required = false) MinioClient minioClient, MinioProperties minioProperties) {
        this.minioClient = Optional.ofNullable(minioClient);
        this.minioProperties = minioProperties;
    }
    
    /**
     * 检查MinIO客户端是否可用
     */
    private void checkClientAvailable() {
        if (!minioClient.isPresent()) {
            throw new RuntimeException("MinIO客户端未配置或配置不正确，请检查application.yaml中的minio配置");
        }
    }
    
    /**
     * 获取所有对象列表
     * 
     * @return 对象名称列表
     */
    public List<String> listObjects() {
        checkClientAvailable();
        List<String> objectNames = new ArrayList<>();
        try {
            Iterable<Result<Item>> results = minioClient.get().listObjects(
                    ListObjectsArgs.builder()
                            .bucket(minioProperties.getBucketName())
                            .recursive(true)
                            .build()
            );
            
            for (Result<Item> result : results) {
                Item item = result.get();
                if (!item.isDir()) {
                    objectNames.add(item.objectName());
                }
            }
            
            log.info("从MinIO获取到 {} 个对象", objectNames.size());
            return objectNames;
        } catch (Exception e) {
            log.error("获取MinIO对象列表失败", e);
            throw new RuntimeException("获取MinIO对象列表失败", e);
        }
    }
    
    /**
     * 根据前缀获取对象列表
     * 
     * @param prefix 对象名前缀
     * @return 对象名称列表
     */
    public List<String> listObjects(String prefix) {
        checkClientAvailable();
        List<String> objectNames = new ArrayList<>();
        try {
            Iterable<Result<Item>> results = minioClient.get().listObjects(
                    ListObjectsArgs.builder()
                            .bucket(minioProperties.getBucketName())
                            .prefix(prefix)
                            .recursive(true)
                            .build()
            );
            
            for (Result<Item> result : results) {
                Item item = result.get();
                if (!item.isDir()) {
                    objectNames.add(item.objectName());
                }
            }
            
            log.info("从MinIO获取到前缀为 '{}' 的 {} 个对象", prefix, objectNames.size());
            return objectNames;
        } catch (Exception e) {
            log.error("获取MinIO对象列表失败，前缀: {}", prefix, e);
            throw new RuntimeException("获取MinIO对象列表失败", e);
        }
    }
    
    /**
     * 下载对象
     * 
     * @param objectName 对象名称
     * @return 对象输入流
     */
    public InputStream downloadObject(String objectName) {
        checkClientAvailable();
        try {
            InputStream inputStream = minioClient.get().getObject(
                    GetObjectArgs.builder()
                            .bucket(minioProperties.getBucketName())
                            .object(objectName)
                            .build()
            );
            
            log.debug("成功下载MinIO对象: {}", objectName);
            return inputStream;
        } catch (Exception e) {
            log.error("下载MinIO对象失败: {}", objectName, e);
            throw new RuntimeException("下载MinIO对象失败: " + objectName, e);
        }
    }
    
    /**
     * 检查存储桶是否存在
     * 
     * @return 存储桶是否存在
     */
    public boolean bucketExists() {
        checkClientAvailable();
        try {
            return minioClient.get().bucketExists(
                    io.minio.BucketExistsArgs.builder()
                            .bucket(minioProperties.getBucketName())
                            .build()
            );
        } catch (Exception e) {
            log.error("检查MinIO存储桶是否存在失败", e);
            return false;
        }
    }
}